#include "httpconn.h"
using namespace std;

const char* HttpConn::srcDir;
std::atomic<int> HttpConn::userCount;
bool HttpConn::isET;

HttpConn::HttpConn() {
    fd_ = -1;
    addr_ = { 0 };
    isClose_ = true;
}

HttpConn::~HttpConn() {
    Close();
}

void HttpConn::init(int fd, const sockaddr_in& addr) {
    assert(fd > 0);
    userCount++;
    addr_ = addr;
    fd_ = fd;
    writeBuff_.RetriveAll(); //将缓冲区清空
    readBuff_.RetriveAll();
    isClose_ = false;
    //显示客户端的ip与端口信息
    LOG_INFO("Client[%d](%s:%d) in, userCount:%d", fd_, GetIP(), GetPort(), (int)userCount);

}

void HttpConn::Close() {
    response_.UnmapFile(); //关闭内存映射
    if(isClose_ == false) {
        isClose_ = true;   //关闭状态
        userCount--;        //用户数--
        close(fd_);         //关闭对应的socket描述符
        LOG_INFO("Client[%d](%s:%d) quit, UserCount:%d", fd_, GetIP(), GetPort(), static_cast<int>(userCount));
    }
}

int HttpConn::GetFd() const {
    return fd_;
}

const char* HttpConn::GetIP() const {
    return inet_ntoa(addr_.sin_addr);   //进行字节序的转换
}

int HttpConn::GetPort() const {
    return addr_.sin_port;
}

ssize_t HttpConn::read(int* saveErro) {
    ssize_t len = -1;
    do {
        len = readBuff_.ReadFd(fd_, saveErro);  //从fd_读取请求到读缓冲
        if(len <= 0) {
            break;
        }
    }
    while(isET);
    return len;
}

ssize_t HttpConn::write(int* saveErrno) {
    ssize_t len = -1;
    do {
        len = writev(fd_, iov_, iovCnt_);  //从fd中写入
        if(len <= 0) {
            *saveErrno = errno;//保存错误信息
            break;
        }

        if(iov_[0].iov_len + iov_[1].iov_len == 0) {break;}     //传输结束
        else if(static_cast<size_t>(len) > iov_[0].iov_len) {   //还有数据没写
            //变换基地址到当前要写的地址
            iov_[1].iov_base = (uint8_t*) iov_[1].iov_base + (len - iov_[0].iov_len);
            iov_[1].iov_len -= (len - iov_[0].iov_len); //当前还要写的长度
            if(iov_[0].iov_len) {
                writeBuff_.RetriveAll();
                iov_[0].iov_len = 0;
            }
        } else {
            iov_[0].iov_base = (uint8_t*)iov_[0].iov_base + len;
            iov_[0].iov_len -= len;
            writeBuff_.Retrive(len);
        }
    }
    while(isET || ToWriteBytes() > 1024);
    return len;
}

bool HttpConn::process() {
    std::string str = readBuff_.RetriveAllToStrConst();
    LOG_INFO("read http size: %d\n, str :\n%s\n", str.size(), str.c_str());
    LOG_INFO("readBuff_.ReadableBytes() : %d\n", readBuff_.ReadableBytes());
    request_.Init(); //初始化请求
    if(readBuff_.ReadableBytes() <= 0) {
        return false;
    } else if(request_.parse(readBuff_)) {
        LOG_DEBUG("\nguan\n %s", request_.path().c_str());
        response_.Init(srcDir, request_.path(), request_.IsKeepAlive(), 200);
    } else {
        response_.Init(srcDir, request_.path(), false, 400);
    }

    // 进行响应报文写入
    response_.MakeResponse(writeBuff_);
    iov_[0].iov_base = const_cast<char*>(writeBuff_.Peek());
    iov_[0].iov_len = writeBuff_.ReadableBytes();
    iovCnt_ = 1;

    // 共享内存
    if(response_.FileLen() > 0 && response_.File()) {
        iov_[1].iov_base = response_.File();
        iov_[1].iov_len = response_.FileLen();
        iovCnt_ = 2;
    }
    LOG_DEBUG("filename:%d, %d to %d", response_.FileLen(), iovCnt_, ToWriteBytes());
    
    return true;
}